package com.dynamic.mybatis.web.util;

import com.dynamic.mybatis.core.metadata.DynamicMappedStatement;
import com.dynamic.mybatis.core.metadata.MappedStatementMetaField;
import com.dynamic.mybatis.core.utils.CollectionUtils;
import com.dynamic.mybatis.core.utils.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;

public class HtmlTemplateUtils {
    private final static int BEGIN_INDEX = 0;
    private final static int BEGIN_LEVEL = 1;
    private final static String API_ITEM_PREFIX = "api-item-";

    private final static String INPUT_HEAD_NAME = "请求头";
    private final static String INPUT_PARAMETER_NAME = "请求参数";
    private final static String OUT_PARAMETER_NAME = "响应参数";


    private final static Map<String, TableColumn> head = new HashMap() {
        {
            put("field", new TableColumn("键", "center", "middle", filed -> Objects.toString(filed.getField(), "")));
            put("defaultValue", new TableColumn("值", "center", "middle", filed -> Objects.toString(filed.getDefaultValue(), "")));
            put("name", new TableColumn("名称", "center", "middle", filed -> Objects.toString(filed.getName())));
            put("validator.required", new TableColumn("必填", "center", "middle", filed -> filed.getValidator() != null && filed.getValidator().isRequired() ? "是" : "否"));
            put("remarks", new TableColumn("备注", "center", "middle", (filed) -> Objects.toString(filed.getRemarks(), "").replaceAll("[\r\n|\n]+", "</br>")));
        }
    };


    private final static Map<String, TableColumn> parameter = new HashMap() {
        {
            put("field", new TableColumn("参数", "left", "middle", filed -> Objects.toString(filed.getField(), "")));
            put("name", new TableColumn("名称", "center", "middle", filed -> Objects.toString(filed.getName(), "")));
            put("mergeType", new TableColumn("类型", "center", "middle", (filed) -> {
                String type = Objects.toString(filed.getType(), "");
                if (StringUtils.isNotEmpty(type)) {
                    type = StringUtils.isNotEmpty(filed.getGenericType()) ? type + "(" + filed.getGenericType() + ")" : type;
                }
                return type;
            }));
            put("validator.required", new TableColumn("必填", "center", "middle", filed -> filed.getValidator() != null && filed.getValidator().isRequired() ? "是" : "否"));
            put("remarks", new TableColumn("备注", "center", "middle", (filed) -> Objects.toString(filed.getRemarks(), "").replaceAll("[\r\n|\n]+", "</br>")));
        }
    };

    static class TableColumn {
        String name;
        String align;
        String valign;
        Function<MappedStatementMetaField, Object> formatter;

        public TableColumn(String name, String align, String valign, Function<MappedStatementMetaField, Object> formatter) {
            this.name = name;
            this.align = align;
            this.valign = valign;
            this.formatter = formatter;
        }

        public String getAlign() {
            return align;
        }

        public void setAlign(String align) {
            this.align = align;
        }

        public String getValign() {
            return valign;
        }

        public void setValign(String valign) {
            this.valign = valign;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Function<MappedStatementMetaField, Object> getFormatter() {
            return formatter;
        }

        public void setFormatter(Function<MappedStatementMetaField, Object> formatter) {
            this.formatter = formatter;
        }
    }

    public static String htmlBuilder(List<DynamicMappedStatement> dms) {
        StringBuilder builder = new StringBuilder();
        bookmarksBuilder(dms, builder);
        apiBuilder(dms, builder);
        return builder.toString();
    }


    public static String bookmarksBuilder(List<DynamicMappedStatement> dms, StringBuilder builder) {
        builder.append("<bookmarks>");
        bookmarkBuilder(dms, BEGIN_INDEX, BEGIN_LEVEL, builder);
        builder.append("</bookmarks>");
        return builder.toString();
    }

    private static void bookmarkBuilder(List<DynamicMappedStatement> dms, int index, int level, StringBuilder builder) {
        for (DynamicMappedStatement d : dms) {
            builder.append("<bookmark name=\"" + d.getName() + "\" href=\"#" + API_ITEM_PREFIX + level + "." + (++index) + "\">");
            if (CollectionUtils.isNotEmpty(d.getChildren())) {
                bookmarkBuilder(d.getChildren(), BEGIN_INDEX, level + 1, builder);
            }
            builder.append("</bookmark>");
        }
    }

    public static void apiBuilder(List<DynamicMappedStatement> dms, StringBuilder builder) {
        builder.append("<div id=\"api-container\" class=\"col-sm-12 api-container\">");
        apiItemBuilder(dms, BEGIN_INDEX, BEGIN_LEVEL, builder);
        builder.append("/<div>");
    }

    private static void apiItemBuilder(List<DynamicMappedStatement> dms, int index, int level, StringBuilder builder) {
        for (DynamicMappedStatement d : dms) {
            apiItemBuilder(d, ++index, level, builder);
        }
    }

    private static void apiItemBuilder(DynamicMappedStatement d, int index, int level, StringBuilder builder) {
        builder.append("<div class=\"" + API_ITEM_PREFIX + "\" id=\"" + API_ITEM_PREFIX + level + "." + index + "\">");
        //表单标题
        builder.append("<form>");

        builder.append("<div class=\"form-group row\">");
        builder.append("<label class=\"col-sm-6 col-form-label col-form-label-name\">" + d.getName() + "</label>");
        builder.append("</div>");

        builder.append("<div class=\"form-group row\">");
        builder.append("<span class=\"col-sm-2 col-form-label col-form-label-name\">" + d.getMethod() + "</span>");
        String url = "/" + Objects.toString(d.getId(), "").replaceAll("\\.", "/");
        builder.append("</span><span class=\"col-sm-8 col-form-label col-form-label-name\">" + url + "</span>");
        builder.append("</div>");

        builder.append("</form>");

        //请求头
        tableBuilder(INPUT_HEAD_NAME, false, level, head, d.getRequestHeader(), builder);
        //请求参数
        tableBuilder(INPUT_PARAMETER_NAME, true, level, parameter, d.getInputParameter(), builder);
        //响应参数
        tableBuilder(OUT_PARAMETER_NAME, true, level, parameter, d.getOutputParameter(), builder);
        builder.append("</div>");

        if (CollectionUtils.isNotEmpty(d.getChildren())) {
            apiItemBuilder(d.getChildren(), BEGIN_INDEX, level + 1, builder);
        }
    }


    private static void tableBuilder(String title, boolean expand, int level, Map<String, TableColumn> table, List<MappedStatementMetaField> fields, StringBuilder builder) {
        builder.append("<div class=\"api-box-table\">");
        builder.append("<h5>" + title + "</h5>");
        builder.append("<div class=\"bootstrap-tree-table\">");
        builder.append("<div class=\"treetable-bars\">");
        builder.append("<div class=\"btn-group tool-right\"></div>");
        builder.append("</div>");
        builder.append("<div class=\"treetable-box treetable-bordered\" style=\"width: 100%;\">");
        builder.append("<div class=\"treetable-fixed treetable-head-box\" style=\"left: 0px;\">");
        builder.append("<table  class=\"api-parameter table treetable-table table-striped\" style=\"width: auto;\">");
        builder.append("<thead class=\"treetable-thead\">");
        builder.append("<tr>");
        for (Map.Entry<String, TableColumn> entry : table.entrySet()) {
            builder.append("<th >" + entry.getValue().getName() + "</th>");
        }
        builder.append("</tr>");
        builder.append("</thead>");
        builder.append("</table>");
        builder.append("</div>");


        builder.append("<div class=\"treetable-body-box\" style=\"border-bottom: 0px; margin-top: 51px;\">");
        builder.append("<table id=\"requestHeaderTable0\" class=\"api-parameter table treetable-table table-striped\">");
        builder.append("<thead class=\"treetable-thead\">");
        builder.append("</thead>");
        builder.append("<tbody class=\"treetable-tbody\">");

        fieldBuilder(expand, BEGIN_INDEX, level, table, fields, builder);

        builder.append("</tbody>");
        builder.append("</table>");
        builder.append("</div>");
        builder.append("</div>");
        builder.append("</div>");
        builder.append("</div>");
    }

    private static void fieldBuilder(boolean expand, int index, int level, Map<String, TableColumn> table, List<MappedStatementMetaField> fields, StringBuilder builder) {
        if (CollectionUtils.isNotEmpty(fields)) {
            for (MappedStatementMetaField field : fields) {
                fieldBuilder(expand, ++index, level, table, field, builder);
            }
        }
    }

    private static void fieldBuilder(boolean expand, int index, int level, Map<String, TableColumn> table, MappedStatementMetaField field, StringBuilder builder) {
        builder.append("<tr  style=\"display: table;\">");
        int i = 0;
        for (Map.Entry<String, TableColumn> entry : table.entrySet()) {
            TableColumn column = entry.getValue();
            Object value = column.getFormatter().apply(field);
            builder.append("<td class=\"ellipsis\" title=\"" + value + "\" nowrap style=\"text-align: " + column.getAlign() + "; vertical-align: " + column.getValign() + ";\">");
            if (i++ == 0) {
                if (level > 0) {
                    //j < level-1 可设置为 j < level ；删除下方添加的treetable-expander 缩小扩展的单元格空白区域
                    for (int j = 0; j < level - 1; j++) {
                        builder.append("<span class=\"treetable-indent\"></span>");
                    }
                }
                if ((expand || CollectionUtils.isNotEmpty(field.getChildren()))) {
                    builder.append("<span class=\"treetable-expander bstt-icon bstt-chevron-down\"></span>");
                } else {
                    builder.append("<span class=\"treetable-expander\"></span>");
                }
            }
            builder.append(value + "</td>");
        }
        builder.append("</tr>");
        if (CollectionUtils.isNotEmpty(field.getChildren())) {
            fieldBuilder(false, index, level + 1, table, field.getChildren(), builder);
        }
    }

}
